import os, sys
import re
import subprocess

root_path = "/home/android/Documents/google_patch"

# "/home/android/Platform/Platform_4901/LINUX/android"
project_path = "/home/android/Platform/Platform_4901_sfr_2/LINUX/android"

shell_path = "/home/android/Opensource/WorkSpace_Py/GooglePatchFilter/gitapply.sh"

csv_path = "/home/android/Opensource/WorkSpace_Py/GooglePatchFilter/Platform_4901_sfr_2-2_11-12.csv"


def handle_patch_file(base_git, patch_file):
    with open(patch_file) as f:
        f_lines = f.readlines()

        if os.path.exists(patch_file + "bk"):
            os.remove(patch_file + "bk")
        with open(patch_file + "bk", "w+") as fbk:
            base_git_split = base_git.strip().split("/")
            # git_last_dir_name = base_git_split[len(base_git_split) - 1]
            # print(git_last_dir_name)
            patch_file_split = os.path.abspath(os.path.join(patch_file, "..")).strip().split("/")

            for f_line in f_lines:
                # diff --git a/framesequence/jni/FrameSequence_webp.cpp b/framesequence/jni/FrameSequence_webp.cpp
                if f_line.startswith("diff --git a/"):
                    ab_path = f_line[11:].split(" ")
                    a_path = ab_path[0].strip()
                    path = a_path[2:]
                    ret, fix_path = append_to_exist_path(base_git, patch_file_split, path)
                    if ret >= 0:
                        write_line = "diff --git a/" + fix_path + " " + "b/" + fix_path + os.linesep
                        fbk.write(write_line)
                    else:
                        assert 1
                        # b_path = ab_path[1].strip()
                        # path = b_path[2:]
                        # ret, fix_b_path = append_to_exist_path(base_git, patch_file_split, path)
                        # if ret >= 0:
                        #     write_line = "diff --git a/" + fix_path + " " + "b/" + fix_path
                        #     fbk.write(write_line)
                        # else:
                        #     assert 2
                elif f_line.startswith("--- a/"):
                    path = f_line.strip()[6:]
                    ret, fix_path = append_to_exist_path(base_git, patch_file_split, path)
                    if ret >= 0:
                        write_line = "--- a/" + fix_path + os.linesep
                        fbk.write(write_line)
                    else:
                        assert 2
                elif f_line.startswith("+++ b/"):
                    path = f_line.strip()[6:]
                    ret, fix_path = append_to_exist_path(base_git, patch_file_split, path)
                    if ret >= 0:
                        write_line = "+++ b/" + fix_path + os.linesep
                        fbk.write(write_line)
                    else:
                        assert 3
                else:
                    fbk.write(f_line)
            fbk.close()
        f.close()


def append_to_exist_path(base_git, patch_file_split, path):
    if os.path.isfile(os.path.join(base_git, path)):
        return 0, path
    temp_path = path
    for a_i in range(len(patch_file_split), 0, -1):
        # sub_dir = patch_file_split[i]
        for a_j in range(a_i - 1, 0, -1):
            temp_path = os.path.join(patch_file_split[a_j], temp_path)
            # print(temp_path)
            check_path = os.path.join(base_git, temp_path)
            # print(check_path)
            if os.path.isfile(check_path):
                return 1, temp_path
    return -1, path


if __name__ == '__main__':
    bool_commit = True

    if os.path.exists(csv_path):
        os.remove(csv_path)
    with open(csv_path, "w+") as csv_info_f:

        csv_info_line = "html" + ","
        csv_info_line = csv_info_line + "cve name" + ","
        csv_info_line = csv_info_line + "Level" + ","
        csv_info_line = csv_info_line + "patch identifier" + ","
        csv_info_line = csv_info_line + "base git path" + ","
        csv_info_line = csv_info_line + "patch path" + ","
        csv_info_line = csv_info_line + "patch result" + ","
        csv_info_f.write(csv_info_line + os.linesep)
        csv_info_f.flush()

        files = disk_walk(root_path).paths()
        files.sort()

        all_info = []

        all_count = 0
        patched_count = 0

        for file in files:
            type_name = os.path.splitext(file)[1]
            if type_name == ".Identifier":
                print("rm file %s " % file)
                os.remove(file)
            elif type_name == ".html":
                file_object = open(file)
                content = file_object.read()
                file_object.close()
                # print(content)
                print("++++++++++++++++++++++++")
                print("from file %s" % file)
                matches = re.search(
                    r'later must address the following issues.</p>(.*?)<table class="table-style-one">(.*?)<h3',
                    content, re.M | re.S | re.DOTALL)
                # print(matches.group(0))
                items = re.search(r'<tbody>(.*?)</tbody>', matches.group(0), re.M | re.S | re.DOTALL)
                # print(items.group(0))
                matches = re.findall(r'<td>(.*?)</td>', items.group(0), re.M | re.S | re.DOTALL)
                # items = matches.groups()

                all_cve = []

                for item in matches:
                    if item.startswith("CVE"):
                        if "," in item:
                            names = item.split(",")
                            for name in names:
                                # print(name.strip())
                                all_cve.append(name.strip())
                        else:
                            # print(item.strip())
                            all_cve.append(item.strip())

                            # pattern = r'<td>' + item + '</td></tr>'
                            # cve_patch_names = re.findall(pattern, content, re.M | re.S | re.DOTALL)
                            # print(item, pattern)
                            # print(cve_patch_names)
                print(all_cve)

                file_object = open(file)
                lines = file_object.readlines()
                for cve in all_cve:
                    for i in range(len(lines)):
                        line = lines[i]
                        cve = cve[cve.find("CVE"):]
                        if cve in line:
                            temp = []
                            temp.append(lines[i - 2])
                            temp.append(lines[i - 1])
                            temp.append(lines[i - 0])
                            temp.append(lines[i + 1])
                            temp.append(lines[i + 2])
                            temp.append(lines[i + 3])
                            temp.append(lines[i + 4])
                            version_in = None
                            level_in = None
                            patch_name = None
                            for aaa in temp:
                                if "6.0.1" in aaa:
                                    version_in = aaa.strip()
                                elif "Critical" in aaa or "High" in aaa:
                                    level_in = aaa.strip()
                                elif "A-" in aaa:
                                    patch_name = aaa.strip()

                                if level_in and version_in and patch_name:
                                    all_count = all_count + 1
                                    print("$$$$$$$$$$$$$$$$$ cve %s index %s" % (cve, all_count))
                                    print(version_in)
                                    print(level_in)
                                    print(patch_name)

                                    parent_dir = os.path.abspath(os.path.join(file, ".."))

                                    subdir_names = disk_walk(parent_dir).paths()
                                    for sub_name in subdir_names:
                                        # print("ssss", sub_name)
                                        # print("bbbbaa", patch_name.strip()[6: -5])
                                        if str(patch_name.strip()[6: -5]) in str(sub_name):
                                            # print("get patch name is ", sub_name)
                                            patch_apply_path = sub_name
                                            with open(sub_name) as f:
                                                all_lines = f.readlines()
                                                for xxx in all_lines:
                                                    if "android-6.0.1_r20" in xxx:
                                                        # print("patch git", xxx)
                                                        ccc = xxx.split("/")
                                                        # print("ccc", ccc)
                                                        base_git = project_path
                                                        for q in range(2, len(ccc)):
                                                            base_git = os.path.join(base_git, ccc[q].strip())
                                                        for q in range(2, len(ccc)):
                                                            base_git = os.path.abspath(os.path.join(base_git, ".."))
                                                            if os.path.isdir(base_git):
                                                                nnn = os.path.join(base_git, ".git")
                                                                if os.path.isdir(nnn):
                                                                    # print("is git ", nnn)
                                                                    patch_real_path = os.path.abspath(
                                                                        os.path.join(sub_name, "..", ".."))
                                                                    # print("patch_real_path0", patch_real_path)
                                                                    patch_real_path = os.path.join(patch_real_path,
                                                                                                   xxx).strip()
                                                                    # print("patch_real_path01", patch_real_path)

                                                                    csv_info_line = file + ","
                                                                    csv_info_line = csv_info_line + cve + ","
                                                                    csv_info_line = csv_info_line + level_in + ","
                                                                    csv_info_line = csv_info_line + patch_name + ","
                                                                    csv_info_line = csv_info_line + base_git + ","
                                                                    csv_info_line = csv_info_line + xxx.strip() + ","

                                                                    try:
                                                                        handle_patch_file(base_git, patch_real_path)
                                                                    except:
                                                                        print("patch %s failed", patch_real_path)
                                                                        csv_info_line = csv_info_line + "Fail" + ","
                                                                        csv_info_f.write(csv_info_line + os.linesep)
                                                                        csv_info_f.flush()
                                                                        break
                                                                    commit_str = patch_real_path.split("/")
                                                                    commit_str = cve + commit_str[len(commit_str) - 1]
                                                                    execute_cmd = shell_path + " " + base_git + " " + patch_real_path + "bk" + " " + commit_str  # + " " + "false"
                                                                    print("execute_cmd", execute_cmd)
                                                                    print("base_git", base_git)
                                                                    print("patch_real_path", patch_real_path + "bk")
                                                                    print("commit_str", commit_str)
                                                                    # if "android/frameworks" in base_git:
                                                                    if not bool_commit:
                                                                        print("not commit patch path:%s" % (
                                                                            patch_real_path))
                                                                        patched_count = patched_count + 1
                                                                        csv_info_line = csv_info_line + "NotCommit" + ","
                                                                        csv_info_f.write(csv_info_line + os.linesep)
                                                                        csv_info_f.flush()
                                                                    else:
                                                                        try:
                                                                            ret = subprocess.check_output(execute_cmd,
                                                                                                          shell=True)
                                                                            print(
                                                                                        "patch success ret:%s patch path:%s" % (
                                                                                    ret, patch_real_path))
                                                                            patched_count = patched_count + 1
                                                                            csv_info_line = csv_info_line + "Success" + ","
                                                                            csv_info_f.write(csv_info_line + os.linesep)
                                                                            csv_info_f.flush()
                                                                        except:
                                                                            print(
                                                                                        "patch failed patch path:%s" % patch_real_path)
                                                                            csv_info_line = csv_info_line + "Fail" + ","
                                                                            csv_info_f.write(csv_info_line + os.linesep)
                                                                            csv_info_f.flush()
                                                                        break
                                                                        # else:
                                                                        #     print("not frameworks git %s " % base_git)
                                                                        #     break

                                                        break
                                    print("**************")
                                    break

                file_object.close()
                print("------------------------")
        print("all patch count %s, success count %s" % (all_count, patched_count))

        csv_info_f.flush()
        csv_info_f.close()
